package com.yc.config;

import com.yc.service.ToolServices;
import dev.langchain4j.community.model.dashscope.QwenEmbeddingModel;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.parser.TextDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentByLineSplitter;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.*;
import dev.langchain4j.service.tool.ToolProvider;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.elasticsearch.ElasticsearchEmbeddingStore;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import org.jspecify.annotations.NonNull;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;


@Configuration
public class AiConfig {
    //带记忆、区分用户、支持流式会话
    public interface Assistant{
        @SystemMessage("你是一位电商网站的客服")
        String chat(@MemoryId String memoryId, @UserMessage String question );  // 需要有一个ChatModel
        @SystemMessage("你是一位电商网站的客服")
        TokenStream chatStream( @MemoryId String memoryId, @UserMessage String question );  //需要有一个StreamingChatModel

    }

//    @Bean
//    public InMemoryEmbeddingStore<TextSegment> embeddingStore() {
//        return new InMemoryEmbeddingStore<>();
//    }

    /**
     *
     * @param chatModel  非流式 AI 聊天模型（如 OpenAI 的 ChatGPT）
     * @param streamingChatModel 流式AI聊天模型（支持实时流式响应）
     * @param chatMemoryStore 聊天记忆存储（用于持久化对话历史）
     */
    @Bean   // 生成代理类对象，这个对象要被spring托管 ->才能注入到Controller
    public Assistant assistant(ChatModel chatModel,
                               StreamingChatModel streamingChatModel,
                               ChatMemoryStore chatMemoryStore, ToolServices tools,
                               EmbeddingStore embeddingStore,
                               QwenEmbeddingModel qwenEmbeddingModel,
                               ToolProvider toolProvider){

//        PersistentChatMemoryStore persistentChatMemoryStore = new PersistentChatMemoryStore();
        //每次对话创建一个独立的记忆窗口，存储历史消息，支持上下文关联
        ChatMemoryProvider chatMemoryProvider= memoryId-> MessageWindowChatMemory.builder()
                .id(   memoryId )
                .maxMessages(1000)
                .chatMemoryStore(   chatMemoryStore )
                .build();

        EmbeddingStoreContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
                .embeddingModel(qwenEmbeddingModel)
                .embeddingStore(embeddingStore)
                .build();
        //使用 Assistant 接口动态生成一个代理类 处理 AI 模型调用、记忆管理、流式响应
        Assistant assistant= AiServices.builder(Assistant.class)
                .chatModel(  chatModel )
                .streamingChatModel( streamingChatModel  )
                .chatMemoryProvider(  chatMemoryProvider )
                .tools(  tools )    //工具
                .toolProvider(toolProvider )
                .contentRetriever(retriever)
                .build();
        return assistant;
     }

//    @Bean
//    public InMemoryEmbeddingStore embeddingStore() {
//        List<Document> documents = FileSystemDocumentLoader.loadDocuments("E:\\testdocuments");
//        InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
//        EmbeddingStoreIngestor.ingest(documents, embeddingStore);
//
//       return embeddingStore;
//    }

    //初始化向量数据库 Elasticsearch
    @Bean
    public CommandLineRunner initDataToVectorStore(
            QwenEmbeddingModel qwenEmbeddingModel,
            ElasticsearchEmbeddingStore elasticsearchEmbeddingStore) throws Exception {
        URL url = getClass().getClassLoader().getResource("rag/b.txt");
        if (url == null) throw new IllegalStateException("资源 rag/b.txt 未找到");
        Path documentPath = Paths.get(url.toURI());

        return args -> {
            Document doc = FileSystemDocumentLoader.loadDocument(documentPath, new TextDocumentParser());
            List<TextSegment> segments = new DocumentByLineSplitter(100, 20).split(doc);
            @NonNull List<Embedding> embeddings = qwenEmbeddingModel.embedAll(segments).content();

            for (int i = 0; i < embeddings.size(); i++) {
                elasticsearchEmbeddingStore.add(embeddings.get(i), segments.get(i));
            }
            System.out.printf("已初始化 ES 向量：%d 条%n", embeddings.size());
        };
    }

}
